package main

import "fmt"

type Component1 interface {
	Calc() int
}

type ConcreteComponent struct{}

func (*ConcreteComponent) Calc() int {
	return 0
}

type MulDecorator struct {
	Component1
	num int
}

func WarpMulDecorator(c Component1, num int) Component1 {
	return &MulDecorator{
		Component1: c,
		num:        num,
	}
}

func (d *MulDecorator) Calc() int {
	fmt.Println("第一步装饰")
	return d.Component1.Calc() * d.num
}

type AddDecorator struct {
	Component1
	num int
}

func WarpAddDecorator(c Component1, num int) Component1 {
	return &AddDecorator{
		Component1: c,
		num:        num,
	}
}

func (d *AddDecorator) Calc() int {
	fmt.Println("第二步装饰")
	return d.Component1.Calc() + d.num
}

func main() {
	var c Component1
	c = &ConcreteComponent{}
	c = WarpAddDecorator(c, 10) // 加10
	c = WarpMulDecorator(c, 8)  // 乘以 8
	resp := c.Calc()

	fmt.Printf("res %d\n", resp)
	// Output:
	// res 80
}

/*

装饰模式

在软件开发过程中，有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下，可以动态地扩展其功能。所有这些都可以釆用装饰模式来实现。

装饰（Decorator）模式的定义：
	指在不改变现有对象结构的情况下，动态地给该对象增加一些职责（即增加其额外功能）的模式，它属于对象结构型模式。

装饰（Decorator）模式的主要优点有：
	采用装饰模式扩展对象的功能比采用继承方式更加灵活。
	可以设计出多个不同的具体装饰类，创造出多个不同行为的组合。

其主要缺点是：
	装饰模式增加了许多子类，如果过度使用会使程序变得很复杂。


# 装饰模式

	装饰模式使用对象组合的方式动态改变或增加对象行为。

	Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。

	使用匿名组合，在装饰器中不必显式定义转调原对象方法。




*/
